package com.baidu.elinkagescroll.view;

import com.baidu.elinkagescroll.ChildLinkageEvent;
import com.baidu.elinkagescroll.ILinkageScroll;
import com.baidu.elinkagescroll.LinkageScrollHandler;
import com.baidu.elinkagescroll.utils.LogUtil;

import com.ryan.ohos.extension.EstimateHelper;

import ohos.agp.components.*;
import ohos.app.Context;

/**
 * description :
 *
 * @since 2021/7/15
 */
public class LScrollView extends NestedScrollView implements ILinkageScroll, Component.EstimateSizeListener {

    /** 联动滚动事件 */
    private ChildLinkageEvent mLinkageChildrenEvent;

    /**
     * init LScrollView
     *
     * @param context context
     */
    public LScrollView(Context context) {
        this(context, null);
    }

    /**
     * init LScrollView
     *
     * @param context context
     * @param attrSet attrSet
     */
    public LScrollView(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    /**
     * init LScrollView
     *
     * @param context context
     * @param attrSet attrSet
     * @param styleName styleName
     */
    public LScrollView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        setEstimateSizeListener(this);
        setScrolledListener(new ScrolledListener() {
            @Override
            public void onContentScrolled(Component component, int scrollX,
                                            int scrollY,
                                            int oldScrollX,
                                            int oldScrollY) {
                enableScrollBar(Component.AXIS_Y, false);
                // 滚动监听，将必要事件传递给联动容器
                if (!canScroll(DRAG_UP)) {
                    if (mLinkageChildrenEvent != null) {
                        mLinkageChildrenEvent.onContentScrollToTop(LScrollView.this);
                    }
                }

                if (!canScroll(DRAG_DOWN)) {
                    if (mLinkageChildrenEvent != null) {
                        mLinkageChildrenEvent.onContentScrollToBottom(LScrollView.this);
                    }
                }

                if (mLinkageChildrenEvent != null) {
                    mLinkageChildrenEvent.onContentScroll(LScrollView.this);
                }
            }
        });
    }

    @Override
    public boolean onEstimateSize(int widthSpecConfig, int heightSpecConfig) {
        int size = getChildCount();
        int scrollViewHeight = 0;
        for (int i = 0; i < size; i++) {
            Component child = getComponentAt(i);
            int childHeight = 0;
            if (child instanceof DirectionalLayout) {
                int childCount = ((DirectionalLayout) child).getChildCount();
                for (int j = 0; j < childCount; j++) {
                    Component innerChild = ((DirectionalLayout) child).getComponentAt(j);
                    measureChild(innerChild, widthSpecConfig, heightSpecConfig);
                    childHeight += innerChild.getEstimatedHeight();
                }
            }
            measureChild(child, widthSpecConfig, EstimateHelper.getChildMeasureSpec(heightSpecConfig,
                    getPaddingTop() + getPaddingBottom(), childHeight));
            scrollViewHeight += child.getEstimatedHeight();
        }
        setEstimatedSize(EstimateSpec.getSize(widthSpecConfig), scrollViewHeight);
        return true;
    }

    private void measureChild(Component child, int parentWidthMeasureSpec,
                                int parentHeightMeasureSpec) {
        final ComponentContainer.LayoutConfig lp = child.getLayoutConfig();
        LogUtil.loge("measureChildHeight = " + lp.height);
        final int childWidthMeasureSpec = EstimateHelper.getChildMeasureSpec(parentWidthMeasureSpec,
                getPaddingLeft() + getPaddingRight(), lp.width);
        final int childHeightMeasureSpec = EstimateHelper.getChildMeasureSpec(parentHeightMeasureSpec,
                getPaddingTop() + getPaddingBottom(), lp.height);
        child.estimateSize(childWidthMeasureSpec, childHeightMeasureSpec);
    }

    @Override
    public void setChildLinkageEvent(ChildLinkageEvent event) {
        mLinkageChildrenEvent = event;

        if (mLinkageChildrenEvent != null) {
            mLinkageChildrenEvent.onContentScroll(this);
        }
    }

    @Override
    public LinkageScrollHandler provideScrollHandler() {
        return new LinkageScrollHandler() {

            @Override
            public void flingContent(Component target, int velocityY) {
                LScrollView.this.doFlingY(velocityY);
            }

            @Override
            public void scrollContentToTop() {
                LScrollView.this.scrollTo(0, 0);
            }

            @Override
            public void scrollContentToBottom() {
                LScrollView.this.scrollTo(0, getVerticalScrollRange());
            }

            @Override
            public void stopContentScroll(Component target) {
                LScrollView.this.doFlingY(0);
            }

            @Override
            public boolean canScrollVertically(int direction) {
                return LScrollView.this.canScroll(direction);
            }

            @Override
            public boolean isScrollable() {
                return true;
            }

            @Override
            public int getVerticalScrollExtent() {
                return getScrollValue(Component.AXIS_Y);
            }

            @Override
            public int getVerticalScrollOffset() {
                return getScrollbarFadingDelay();
            }

            @Override
            public int getVerticalScrollRange() {
                return getScrollValue(Component.AXIS_Y);
            }
        };
    }
}
